<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Spatie\Permission\Traits\HasRoles;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;

class User extends Authenticatable implements FilamentUser
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable, HasRoles;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'username',
        'password',
        'avatar',
        'bio',
        'role',
        'status',
        'last_login_at',
        'website',
        'github',
        'twitter',
        'linkedin',
        'location',
        'occupation',
        'followers_count',
        'following_count',
        'posts_count',
        'allow_email_notifications',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'last_login_at' => 'datetime',
            'password' => 'hashed',
        ];
    }

    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = ['avatar_url'];

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }

    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class);
    }

    public function likes(): HasMany
    {
        return $this->hasMany(PostLike::class);
    }

    public function favorites(): HasMany
    {
        return $this->hasMany(PostFavorite::class);
    }

    public function customNotifications(): HasMany
    {
        return $this->hasMany(Notification::class);
    }

    public function unreadCustomNotifications()
    {
        return $this->customNotifications()->where('is_read', false);
    }

    public function isAdmin(): bool
    {
        return $this->role === 'admin';
    }

    public function isEditor(): bool
    {
        return in_array($this->role, ['admin', 'editor']);
    }

    public function isAuthor(): bool
    {
        return in_array($this->role, ['admin', 'editor', 'author']);
    }

    public function canPublishPost(): bool
    {
        return $this->isEditor();
    }

    public function getAvatarUrlAttribute(): string
    {
        return $this->avatar
            ? asset('storage/' . $this->avatar)
            : 'https://ui-avatars.com/api/?name=' . urlencode($this->name);
    }

    public function canAccessPanel(Panel $panel): bool
    {
        return in_array($this->role, ['admin', 'editor', 'author']);
    }

    /**
     * 获取我关注的用户
     */
    public function following(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'user_follows', 'follower_id', 'following_id')
                    ->withTimestamps();
    }

    /**
     * 获取关注我的用户
     */
    public function followers(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'user_follows', 'following_id', 'follower_id')
                    ->withTimestamps();
    }

    /**
     * 判断是否关注了某个用户
     */
    public function isFollowing(User $user): bool
    {
        return $this->following()->where('following_id', $user->id)->exists();
    }

    /**
     * 关注用户
     */
    public function follow(User $user): void
    {
        if (!$this->isFollowing($user)) {
            $this->following()->attach($user->id);
            $this->increment('following_count');
            $user->increment('followers_count');
        }
    }

    /**
     * 取消关注用户
     */
    public function unfollow(User $user): void
    {
        if ($this->isFollowing($user)) {
            $this->following()->detach($user->id);
            $this->decrement('following_count');
            $user->decrement('followers_count');
        }
    }

    /**
     * 获取浏览历史
     */
    public function viewedPosts(): BelongsToMany
    {
        return $this->belongsToMany(Post::class, 'post_views')
                    ->withPivot(['viewed_at', 'last_viewed_at', 'view_count', 'read_duration', 'read_progress'])
                    ->orderByPivot('last_viewed_at', 'desc');
    }

    /**
     * 判断用户是否可以查看文章
     */
    public function canViewPost(Post $post): bool
    {
        // 作者可以查看自己的所有文章
        if ($post->user_id === $this->id) {
            return true;
        }

        // 管理员和编辑可以查看所有文章
        if (in_array($this->role, ['admin', 'editor'])) {
            return true;
        }

        // 根据文章权限判断
        switch ($post->access_level) {
            case 'public':
                return true;
            case 'login_required':
                return true; // 已登录用户
            case 'followers_only':
                return $this->isFollowing($post->user);
            case 'private':
                return false;
            default:
                return false;
        }
    }

    /**
     * 获取用户的所有通知
     */
    public function notifications(): \Illuminate\Database\Eloquent\Relations\MorphMany
    {
        return $this->morphMany(Notification::class, 'notifiable')->orderBy('created_at', 'desc');
    }

    /**
     * 获取未读通知
     */
    public function unreadNotifications(): \Illuminate\Database\Eloquent\Relations\MorphMany
    {
        return $this->notifications()->unread();
    }

    /**
     * 发送通知
     */
    public function notify(string $type, array $data): Notification
    {
        return $this->notifications()->create([
            'type' => $type,
            'data' => $data,
        ]);
    }

    /**
     * 标记所有通知为已读
     */
    public function markAllNotificationsAsRead(): void
    {
        $this->unreadNotifications()->update(['read_at' => now()]);
    }

    /**
     * 获取未读通知数量
     */
    public function getUnreadNotificationCountAttribute(): int
    {
        return $this->unreadNotifications()->count();
    }
}
